# -*- coding:utf8 -*-
import datetime
import json
import urllib2
import urllib
from django.conf.urls import url
import time
from wanbatvpayment.http.decorators import require_params
from wanpay.models.common import PayOrder
from wanbatvpayment.http.whttp import send_error_response_on_exception, send_error_response_with_message, \
    send_ok_response_with_data, send_ok_response_with_list

__author__ = 'Forcs'


class PayStatus:
    ADDED = 1
    CANCEL = -1
    DONE = 2
    EXPIRE = 3

SUBJECT_EXPIRE = {
    "M": 30,
    "F": 365,
    "P": 30,
}


class PayService(object):

    def __init__(self):
        self._curr_trade_id = self._next_trade_id()
    
    def _next_trade_id(self):
        today = datetime.date.today()
        next_date = today + datetime.timedelta(days=1)
        orders = PayOrder.objects.filter(date_added__range=(today, next_date))
        return orders.count() + 1

    @property
    def urls(self):
        urlpatterns = [
            url(r'^order/gen$', self.gen_pay_order, name="pay_order_gen"),
            url(r'^order/done$', self.done_pay_order, name="pay_order_done"),
            url(r'^order/cancel$', self.cancel_pay_order, name="pay_order_cancel"),
            url(r'^order/details/(?P<order_field>\w+)$', self.get_pay_order_field, name="get_order_field"),
            url(r'^user/orders/done$', self.get_user_payed, name="user_all_payed_order"),
            url(r'^user/orders$', self.get_user_orders, name="user_all_order"),
            url(r'^payment/auth$', self.auth_payment, name="pay_auth"),
        ]
        return urlpatterns

    @require_params(["stb", "appid"], method="POST")
    def auth_payment(self, request):
        body = request.POST
        stb = body["stb"]
        if stb.find("_") > -1:
            stb = stb.split("_")[1]
        app_id = body["appid"]
        try:
            lookup = {
                "stb_id__contains": stb,
                "status": PayStatus.DONE,
                "app_id": app_id
            }
            if "subjectcode" in body:
                lookup.update({
                    "subject_id": body["subjectcode"]
                })
            order_qs = PayOrder.objects.filter(**lookup)
            result_data = {
                "payCompleted": False,
                "expiration": 0,
                "reason": '',
                "expiretime": ''
            }
            done_order_count = order_qs.count()
            if done_order_count > 0:
                expire_orders = []
                now = datetime.datetime.now()
                expire_datetime = now + datetime.timedelta(days=1)
                date_expire = now
                for order_model in order_qs:
                    date_expire = max(date_expire, order_model.date_expire)
                    if order_model.date_expire < expire_datetime.replace(tzinfo=None):
                        expire_orders.append(order_model)

                expire_order_count = len(expire_orders)
                if expire_order_count > 0:
                    for expire_order in expire_orders:
                        expire_order.status = PayStatus.EXPIRE
                        expire_order.save()

                if expire_order_count < done_order_count:
                    result_data["payCompleted"] = True
                    result_data["expiration"] = int((date_expire - now).total_seconds() / (24 * 3600))
                    result_data["expiretime"] = date_expire.strftime("%Y-%m-%d %H:%M:%S")
                    return send_ok_response_with_data(data=result_data)
                else:
                    result_data["reason"] = u'商品包已过期，需要重新订购'
                    return send_ok_response_with_data(data=result_data)
            else:
                return send_ok_response_with_data(data=result_data)
        except Exception as e:
            return send_error_response_on_exception(e)

    @require_params(["subjectid", "provider", "stb", "flavor", "subjecthost"], method="POST")
    def gen_pay_order(self, request):
        body = request.POST
        subject_id = body["subjectid"]
        subject_host = body["subjecthost"]
        subject_url = 'http://%s/api/common/subject/%s' % (subject_host, subject_id)

        import urllib2
        req = urllib2.Request(subject_url)
        req.add_header("app-version", "2.0.0")

        try:
            res = urllib2.urlopen(req)
            res_content = res.read()
            res.close()
            res_result = json.loads(res_content, encoding='utf8')
            if res_result["resultCode"] == 1:
                res_data = res_result["data"]
                subject = res_data["name"]
                subject_type = res_data["type"]

                try:
                    pay_orders_qs = PayOrder.objects.filter(stb_id__contains=body["stb"],
                                                            status=PayStatus.DONE, app_id=res_data["app"])
                    if pay_orders_qs:
                        total_order_months = 0
                        for pay_order in pay_orders_qs:
                            sub_type = pay_order.subject_type
                            if sub_type == 'M':
                                total_order_months += 1
                            elif sub_type == 'F':
                                total_order_months += 12

                        curr_order_months = total_order_months

                        if subject_type == 'M':
                            total_order_months += 1
                        elif subject_type == 'F':
                            total_order_months += 12

                        if total_order_months > 23:
                            return send_error_response_with_message(
                                message='累计订购时间不能超过23个月，您当前累计订购时间已达%d个月，'
                                        '无法再续订%s' % (curr_order_months, subject),
                                rc=2)

                except:
                    pass

                subject_id = res_data["id"]
                subject_id = '%02d' % subject_id
                trade_id = '%04d' % self._curr_trade_id
                now = datetime.datetime.now()
                timestamp = time.mktime(now.timetuple())
                sec = '%05d' % (now.hour * 3600 + now.minute * 60 + now.second)
                date = now.strftime('%y%m%d')
                check = date + sec
                check_num = 0
                for i, ch in enumerate(check):
                    check_num += int(ch)
                check = str(check_num).zfill(2)
                order_code = '%s%s%s%s%s00%s' % (subject_type, subject_id, date, trade_id, sec, check)

                import hashlib
                md5 = hashlib.md5()
                md5.update('%s%d' % (order_code, timestamp))
                token = md5.hexdigest()

                model, created = PayOrder.objects.get_or_create(code=order_code)
                model.date_added = now
                model.timestamp = timestamp
                model.subject = subject
                model.subject_id = res_data["code"]
                model.subject_type = subject_type
                model.stb_id = body["stb"]
                model.provider = body["provider"]
                model.status = PayStatus.ADDED
                model.token = token
                model.price = int(res_data["price"])
                model.flavor = body["flavor"]
                model.app_id = res_data["app"]
                model.save()

                self._curr_trade_id = self._next_trade_id()

                return send_ok_response_with_data(data={
                    "orderCode": order_code,
                    "tradeId": trade_id
                })
            else:
                return send_error_response_with_message(message=res_result["message"])

        except Exception as e:
            return send_error_response_on_exception(e)

    @require_params(["ordercode"], method="POST")
    def cancel_pay_order(self, request):
        code = request.POST["ordercode"]
        try:
            order_model = PayOrder.objects.get(code=code)
            order_model.status = PayStatus.CANCEL
            order_model.save()

            return send_ok_response_with_data(data={
                "cancelOrder": code
            })
        except Exception as e:
            return send_error_response_on_exception(e)

    @require_params(["ordercode", "provider"], method='POST')
    def done_pay_order(self, request):
        host = request.get_host()
        if host[:-5] == '121.201.14.248':
            host = '121.201.14.248:8062'
        if host[:-5] == '121.201.7.173':
            host = '121.201.7.173:8087'
        body = request.POST
        code = body["ordercode"]

        try:
            order_model = PayOrder.objects.get(code=code, status=PayStatus.ADDED)

            stb_id = order_model.stb_id
            if stb_id.find("_") > -1:
                stb_id = stb_id.split("_")[1]

            now = datetime.datetime.now()
            pre_date_expire = now
            # 检查用户是否有未过期的产品包，如果有，当前订单的有效期将顺延到期日
            if order_model.subject_type != "P":
                curr_user_done_orders_qs = PayOrder.objects.filter(stb_id__contains=stb_id, status=PayStatus.DONE)
                if curr_user_done_orders_qs.count():
                    for done_order in curr_user_done_orders_qs:
                        pre_date_expire = max(pre_date_expire, done_order.date_expire)
            else:
                curr_user_done_orders_qs = PayOrder.objects.filter(stb_id__contains=stb_id,
                                                                   status=PayStatus.DONE,
                                                                   subject_id=order_model.subject_id)
                if curr_user_done_orders_qs.count():
                    for done_order in curr_user_done_orders_qs:
                        pre_date_expire = max(pre_date_expire, done_order.date_expire)

            order_model.status = PayStatus.DONE
            order_model.date_done = now
            subject_expire = SUBJECT_EXPIRE['' + order_model.subject_type]
            order_model.date_expire = pre_date_expire + datetime.timedelta(days=subject_expire)

            keys = body.keys()
            if "tradeid" in keys:
                order_model.provider_trade_id = body["tradeid"]
            if "buyer" in keys:
                order_model.buyer_id = body["buyer"]
            if "autorenew" in keys:
                order_model.auto_renew = bool(body["autorenew"])
            if "begindate" in keys:
                order_model.date_done = datetime.datetime.strptime(body["begindate"], '%Y-%m-%d %H:%M:%S')
            if "enddate" in keys:
                order_model.date_expire = datetime.datetime.strptime(body["enddate"], '%Y-%m-%d %H:%M:%S')

            order_model.save()
            if order_model.subject_type == 'P':
                parms = {
                    'stbid': order_model.stb_id,
                    'subjectid': order_model.subject_id,
                    'dateexpire': order_model.date_expire.strftime("%Y-%m-%d %H:%M:%S"),
                }

                req = urllib2.Request('http://%s/api/bengbengtiao/notify/payedprogram' % host,
                                      data=urllib.urlencode(parms))
                res = urllib2.urlopen(req)
                content = res.read()
                res.close()

            return send_ok_response_with_data(data={
                "orderDone": True,
                "order": order_model.code
            })
        except Exception as e:
            return send_error_response_on_exception(e)

    @require_params(["ordercode"], method='POST')
    def get_pay_order_field(self, request, order_field=None):

        if not order_field:
            return send_error_response_with_message(message='订单字段为空，无法获取订单信息')

        order_code = request.POST["ordercode"]

        try:
            order_info = PayOrder.objects.values('code', order_field).get(code=order_code)
            return send_ok_response_with_data(data=order_info)
        except Exception as e:
            return send_error_response_on_exception(e)

    @require_params(["stb", "appid"], method="POST")
    def get_user_orders(self, request):
        """
        获取设备的所有订单
        """
        body = request.POST
        stb = body["stb"]
        app_id = body["appid"]
        if stb.find("_") > -1:
            stb = stb.split("_")[1]
        try:
            order_qs = PayOrder.objects.filter(stb_id__contains=stb, status__gt=PayStatus.ADDED, app_id=app_id)
            order_list = list()
            order_subjects = list()
            expiration = 0
            now = datetime.datetime.now()
            one_date_seconds = 24 * 3600
            for order in order_qs:
                subject = order.subject
                if subject not in order_subjects:
                    order_subjects.append(subject)
                curr_expiration = int((order.date_expire - now).total_seconds() / one_date_seconds)
                expiration = max(expiration, curr_expiration)
                order_list.append({
                    "code": order.code,
                    "subject": subject,
                    "subjectId": order.subject_id,
                    "price": order.price,
                    "appId": order.app_id,
                    "dateAdded": order.date_added.strftime("%Y-%m-%d %H:%M:%S"),
                    "dateDone": order.date_done.strftime("%Y-%m-%d %H:%M:%S"),
                    "dateExpire": order.date_expire.strftime("%Y-%m-%d %H:%M:%S"),
                    "expiration": expiration,
                })

            expire_msg = u'DOG TV节目将于 %s 到期' % ((now + datetime.timedelta(days=expiration)).strftime("%Y年%m月%d日"))
            if expiration == 2:
                expire_msg = u'DOG TV产品包明天到期啦'
            elif expiration == 1:
                expire_msg = u'DOG TV产品包今天到期啦'
            elif expiration == 0:
                expire_msg = u'DOG TV产品包已经过期'

            return send_ok_response_with_data({
                "list": order_list,
                "subjects": ",".join(order_subjects) if order_subjects else '',
                "expiration": expiration,
                "expMessage": expire_msg,
            })

        except Exception as e:
            return send_error_response_on_exception(e)

    @require_params(["stb", "appid"], method="POST")
    def get_user_payed(self, request):
        """
        获取设备的所有订单
        """
        body = request.POST
        stb = body["stb"]
        app_id = body["appid"]
        if stb.find("_") > -1:
            stb = stb.split("_")[1]
        try:
            order_qs = PayOrder.objects.order_by("-date_expire").filter(stb_id__contains=stb, status=PayStatus.DONE, app_id=app_id)

            order_list = list()
            order_subjects = list()
            expiration = 0
            now = datetime.datetime.now()
            one_date_seconds = 24 * 3600
            for order in order_qs:
                expiration = 0
                subject = order.subject
                if subject not in order_subjects:
                    order_subjects.append(subject)
                    curr_expiration = int((order.date_expire - now).total_seconds() / one_date_seconds)
                    expiration = max(expiration, curr_expiration)
                    order_list.append({
                        "code": order.code,
                        "subject": subject,
                        "subjectId": order.subject_id,
                        "price": '%.2f' % (float(order.price)/100),
                        "appId": order.app_id,
                        "dateAdded": order.date_added.strftime("%Y-%m-%d %H:%M:%S")[0:10],
                        "dateDone": order.date_done.strftime("%Y-%m-%d %H:%M:%S")[0:10],
                        "dateExpire": order.date_expire.strftime("%Y-%m-%d %H:%M:%S")[0:10],
                        "expiration": expiration,
                        "payed": expiration / 30 < 13,
                    })

            return send_ok_response_with_data({
                "list": order_list,
                "subjects": ",".join(order_subjects) if order_subjects else '',
            })

        except Exception as e:
            return send_error_response_on_exception(e)


pay_service = PayService()
